#!/usr/bin/perl -w
require 5.003;

use strict;
use Data::Dumper;
use Win32::SerialPort qw( :STAT 0.19 );
use Getopt::Long;

package main;
sub msg($){my($txt)=@_; print ("$txt\n");}
sub dbg($){my($txt)=@_; msg("[DBG] $txt");}

############################################################################
package GSMModem;
# ---------------------- FUNCTION ------------------------------------------
sub debug($){
	my $DBG = 0;
	if ( $DBG ) {
		my($txt)=@_; $txt="undefined" unless defined($txt); print ("[DEBUG] $txt\n");
	}
}
# ---------------------- FUNCTION ------------------------------------------
sub new($) {
    my ($class) = @_;
    my $self = {
        _comPort       => undef,
        _inputCommand  => undef,
        _output        => undef,
        _isConnected   => undef,
        _isInit        => 0,
        
        _objPort       => undef
    };
    bless $self, $class;
    return $self;	
}
# ---------------------- FUNCTION ------------------------------------------
sub DESTROY {
    my $self = shift;
    # check for an overridden destructor...
    $self->SUPER::DESTROY if $self->can("SUPER::DESTROY");
    # now do your own thing before or after
    if ( $self->{_isInit} ) {
    	$self->_eof();
    	#$self->_request("AT+CFUN=0");
    }
}
# ---------------------- FUNCTION ------------------------------------------
sub comPort {
	my ($self, $port) = @_;
	$self->{_comPort} = $port if defined($port);
	return $self->{_comPort}; 
}
# ---------------------- FUNCTION ------------------------------------------
sub command {
	my ($self, $arg) = @_;
	$self->{_inputCommand} = $arg if defined($arg);
	return $self->{_inputCommand}; 
}
# ---------------------- FUNCTION ------------------------------------------
sub init {
	my ($self) = @_;
	if ( $self->{_objPort} = new Win32::SerialPort ($self->comPort(), 0) )
	{
		$self->{_objPort}->lookclear();
		$self->{_isInit} = 1;
		$self->_request("ATE1");
		$self->_request("AT+CFUN=1");
		$self->{_objPort}->error_msg(1);
		$self->{_objPort}->user_msg(1);
		main::msg($self->_request("AT+COPS?"));
		main::msg("Initialized");
	}
	else
	{
		main::msg("Can't init comport: " . $self->comPort());
		$self->{_isInit} = 0;
	}
	
	
	return $self->{_isInit};
}
# ---------------------- FUNCTION ------------------------------------------
sub _send {
	my ($self, $str) = @_;
	if ( !$self->{_isInit} )
	{
		return;
	}
	$str = $str."\r";
	my $cOut = $self->{_objPort}->write($str);
	debug("-> $str");
	warn "write failed\n"         unless ($cOut);
  	warn "write incomplete\n"     if ( $cOut != length($str) );
	# bytes sent
	return $cOut;
}
# ---------------------- FUNCTION ------------------------------------------
sub _receive {
	my ($self) = @_;
	if ( !$self->{_isInit} )
	{
		return;
	}
	
	my ($count, $result) = (0, "");
	
	while ( index($result, "\nOK\r\n") < 0 && index($result, "\nERROR\r\n") < 0 ) {
		my ($count1, $result1) = $self->{_objPort}->read(4096);
		$count += $count1;
		$result .= $result1;
	} 
	return $result;
}
# ---------------------- FUNCTION ------------------------------------------
sub _request {
	my ($self, $cmd) = @_;
	if ( !$self->{_isInit} )
	{
		return;
	}
	$self->_send($cmd);
	my $r = $self->_receive();
	return $r;
}
# ---------------------- FUNCTION ------------------------------------------
sub _eof {
	my ($self, $cmd) = @_;
	if ( !$self->{_isInit} )
	{
		return;
	}
	$self->_send("\cZ");	
}

############################################################################
package main;
sub readSMS {
	my ($modem) = @_;
	msg ($modem->_request("AT"));
	msg ($modem->_request('AT+CMGL="ALL"'));	
}
# ---------------------- FUNCTION ------------------------------------------
sub sendSMS {
	my ($modem, $to, $message) = @_;
	msg ($modem->_request("AT"));
	msg ($modem->_request("AT+COPS"));
	msg ($modem->_request("AT+CMGF=1"));
	$modem->_send('AT+CMGS="'.$to.'"');
	$modem->_send($message);
	$modem->_eof();
	msg ( $modem->_receive() );
}
############################################################################
############################################################################
# command line parameters
my $comPort = "";
my $command = "";
my $to = "";
my $message = "";
my @getParams = (
	"comPort:s" => \$comPort,
	"command:s" => \$command,
	"to:s" => \$to,
	"message:s" => \$message,
);
GetOptions(@getParams);
############################################################################
my $argc = scalar @ARGV;

my $modem = new GSMModem();

$modem->comPort($comPort);
$modem->command($command);

msg ( "comPort: " . $modem->comPort() );
msg ( "command: " . $modem->command() );

$modem->init();

if ( $command eq "READSMS" ) {
	readSMS($modem);
} elsif ( $command eq "SENDSMS" ) {
	sendSMS($modem, $to, $message);
} else {
	msg("Unknown command: " . $command);
}
